/**
 */
package fUML.Semantics.Activities.IntermediateActivities;

import fUML.Semantics.Activities.CompleteStructuredActivities.StructuredActivityNodeActivation;

import fUML.Syntax.Activities.IntermediateActivities.ActivityEdge;
import fUML.Syntax.Activities.IntermediateActivities.ActivityNode;

import org.eclipse.emf.common.util.EList;

import org.eclipse.emf.ecore.EObject;

/**
 * <!-- begin-user-doc -->
 * A representation of the model object '<em><b>Activity Node Activation Group</b></em>'.
 * <!-- end-user-doc -->
 *
 * <!-- begin-model-doc -->
 * An activity node group is a group of nodes that are activated together, either
 *                 directly in the context of an activity execution, or in the context of 
 * <!-- end-model-doc -->
 *
 * <p>
 * The following features are supported:
 * <ul>
 *   <li>{@link fUML.Semantics.Activities.IntermediateActivities.ActivityNodeActivationGroup#getEdgeInstances <em>Edge Instances</em>}</li>
 *   <li>{@link fUML.Semantics.Activities.IntermediateActivities.ActivityNodeActivationGroup#getNodeActivations <em>Node Activations</em>}</li>
 *   <li>{@link fUML.Semantics.Activities.IntermediateActivities.ActivityNodeActivationGroup#getActivityExecution <em>Activity Execution</em>}</li>
 *   <li>{@link fUML.Semantics.Activities.IntermediateActivities.ActivityNodeActivationGroup#getContainingNodeActivation <em>Containing Node Activation</em>}</li>
 * </ul>
 * </p>
 *
 * @see fUML.Semantics.Activities.IntermediateActivities.IntermediateActivitiesPackage#getActivityNodeActivationGroup()
 * @model
 * @generated
 */
public interface ActivityNodeActivationGroup extends EObject {
	/**
	 * Returns the value of the '<em><b>Edge Instances</b></em>' containment reference list.
	 * The list contents are of type {@link fUML.Semantics.Activities.IntermediateActivities.ActivityEdgeInstance}.
	 * It is bidirectional and its opposite is '{@link fUML.Semantics.Activities.IntermediateActivities.ActivityEdgeInstance#getGroup <em>Group</em>}'.
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * <!-- begin-model-doc -->
	 * The set of activity edge instances for this group. 
	 *  
	 * <!-- end-model-doc -->
	 * @return the value of the '<em>Edge Instances</em>' containment reference list.
	 * @see fUML.Semantics.Activities.IntermediateActivities.IntermediateActivitiesPackage#getActivityNodeActivationGroup_EdgeInstances()
	 * @see fUML.Semantics.Activities.IntermediateActivities.ActivityEdgeInstance#getGroup
	 * @model opposite="group" containment="true" ordered="false"
	 * @generated
	 */
	EList<ActivityEdgeInstance> getEdgeInstances();

	/**
	 * Returns the value of the '<em><b>Node Activations</b></em>' containment reference list.
	 * The list contents are of type {@link fUML.Semantics.Activities.IntermediateActivities.ActivityNodeActivation}.
	 * It is bidirectional and its opposite is '{@link fUML.Semantics.Activities.IntermediateActivities.ActivityNodeActivation#getGroup <em>Group</em>}'.
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * <!-- begin-model-doc -->
	 * The set of activity node executions for this group. 
	 *  
	 * <!-- end-model-doc -->
	 * @return the value of the '<em>Node Activations</em>' containment reference list.
	 * @see fUML.Semantics.Activities.IntermediateActivities.IntermediateActivitiesPackage#getActivityNodeActivationGroup_NodeActivations()
	 * @see fUML.Semantics.Activities.IntermediateActivities.ActivityNodeActivation#getGroup
	 * @model opposite="group" containment="true" ordered="false"
	 * @generated
	 */
	EList<ActivityNodeActivation> getNodeActivations();

	/**
	 * Returns the value of the '<em><b>Activity Execution</b></em>' container reference.
	 * It is bidirectional and its opposite is '{@link fUML.Semantics.Activities.IntermediateActivities.ActivityExecution#getActivationGroup <em>Activation Group</em>}'.
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * <!-- begin-model-doc -->
	 * The activity execution to which this group belongs.
	 *  (This will be
	 *                   empty if the group is for a structured activity node activation.)
	 * <!-- end-model-doc -->
	 * @return the value of the '<em>Activity Execution</em>' container reference.
	 * @see #setActivityExecution(ActivityExecution)
	 * @see fUML.Semantics.Activities.IntermediateActivities.IntermediateActivitiesPackage#getActivityNodeActivationGroup_ActivityExecution()
	 * @see fUML.Semantics.Activities.IntermediateActivities.ActivityExecution#getActivationGroup
	 * @model opposite="activationGroup" transient="false" ordered="false"
	 * @generated
	 */
	ActivityExecution getActivityExecution();

	/**
	 * Sets the value of the '{@link fUML.Semantics.Activities.IntermediateActivities.ActivityNodeActivationGroup#getActivityExecution <em>Activity Execution</em>}' container reference.
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @param value the new value of the '<em>Activity Execution</em>' container reference.
	 * @see #getActivityExecution()
	 * @generated
	 */
	void setActivityExecution(ActivityExecution value);

	/**
	 * Returns the value of the '<em><b>Containing Node Activation</b></em>' container reference.
	 * It is bidirectional and its opposite is '{@link fUML.Semantics.Activities.CompleteStructuredActivities.StructuredActivityNodeActivation#getActivationGroup <em>Activation Group</em>}'.
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * <!-- begin-model-doc -->
	 * The structured activity node activation to which this group belongs.
	 *                   (This will be empty if the group is for an activity execution.)
	 * <!-- end-model-doc -->
	 * @return the value of the '<em>Containing Node Activation</em>' container reference.
	 * @see #setContainingNodeActivation(StructuredActivityNodeActivation)
	 * @see fUML.Semantics.Activities.IntermediateActivities.IntermediateActivitiesPackage#getActivityNodeActivationGroup_ContainingNodeActivation()
	 * @see fUML.Semantics.Activities.CompleteStructuredActivities.StructuredActivityNodeActivation#getActivationGroup
	 * @model opposite="activationGroup" transient="false" ordered="false"
	 * @generated
	 */
	StructuredActivityNodeActivation getContainingNodeActivation();

	/**
	 * Sets the value of the '{@link fUML.Semantics.Activities.IntermediateActivities.ActivityNodeActivationGroup#getContainingNodeActivation <em>Containing Node Activation</em>}' container reference.
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @param value the new value of the '<em>Containing Node Activation</em>' container reference.
	 * @see #getContainingNodeActivation()
	 * @generated
	 */
	void setContainingNodeActivation(StructuredActivityNodeActivation value);

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * <!-- begin-model-doc -->
	 * // Run the given node activations and then (concurrently) send an offer to all
	 *                   activations for nodes with no incoming edges within the given set.
	 *                   
	 *  for (int i = 0; i < activations.size(); i++) {
	 *                   ActivityNodeActivation activation = activations.getValue(i);
	 *                   activation.run();
	 *  }
	 *  
	 *  Debug.println("[run] Checking for
	 *                   enabled nodes...");
	 *  
	 *  ActivityNodeActivationList
	 *                   enabledActivations = new ActivityNodeActivationList(); 
	 *  
	 *  for
	 *                   (int i = 0; i < activations.size(); i++) {
	 *  ActivityNodeActivation
	 *                   activation = activations.getValue(i);
	 *  
	 *  Debug.println("[run]
	 *                   Checking node " + activation.node.name + "...");
	 *  
	 *  if (activation
	 *                   instanceof ActionActivation | 
	 *  activation instanceof
	 *                   ControlNodeActivation | 
	 *  activation instanceof
	 *                   ActivityParameterNodeActivation) {
	 *  
	 *  boolean isEnabled =
	 *                   this.checkIncomingEdges(activation.incomingEdges, activations);
	 *  
	 *                   // For an action activation, also consider incoming edges to input pins
	 *                   if (isEnabled & activation instanceof ActionActivation) {
	 *                   InputPinList inputPins = ((Action)activation.node).input;
	 *  int j =
	 *                   1;
	 *  while (j <= inputPins.size() & isEnabled) {
	 *                   InputPin inputPin = inputPins.getValue(j-1);
	 *  ActivityEdgeInstanceList
	 *                   inputEdges =
	 *                   ((ActionActivation)activation).getPinActivation(inputPin).incomingEdges;
	 *                   isEnabled = this.checkIncomingEdges(inputEdges, activations);
	 *  j = j +
	 *                   1;
	 *  }
	 *  }
	 *  
	 *  if (isEnabled) {
	 *                   Debug.println("[run] Node " + activation.node.name + " is enabled.");
	 *                   enabledActivations.addValue(activation);
	 *  }
	 *  }
	 *  }
	 *                   
	 *  // Debug.println("[run] " + enabledActivations.size() + " node(s) are
	 *                   enabled.");
	 *  
	 *  // *** Send offers to all enabled nodes
	 *                   concurrently. ***
	 *  for (Iterator i = enabledActivations.iterator();
	 *                   i.hasNext();) {
	 *  ActivityNodeActivation activation =
	 *                   (ActivityNodeActivation)i.next();
	 *  Debug.println("[run] Sending offer to
	 *                   node " + activation.node.name + ".");
	 *  activation.receiveOffer();
	 *                   }
	 * <!-- end-model-doc -->
	 * @model activationsMany="true" activationsOrdered="false"
	 * @generated
	 */
	void run(EList<ActivityNodeActivation> activations);

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @model required="true" ordered="false" incomingEdgesMany="true" incomingEdgesOrdered="false" activationsMany="true" activationsOrdered="false"
	 * @generated
	 */
	boolean checkIncomingEdges(EList<ActivityEdgeInstance> incomingEdges, EList<ActivityNodeActivation> activations);

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * <!-- begin-model-doc -->
	 * // Run the node activations associated with the given nodes in this activation
	 *                   group.
	 *  
	 *  ActivityNodeActivationList nodeActivations = new
	 *                   ActivityNodeActivationList();
	 *  
	 *  for (int i = 0; i <
	 *                   nodes.size(); i++) {
	 *  ActivityNode node = nodes.getValue(i);
	 *                   ActivityNodeActivation nodeActivation = this.getNodeActivation(node);
	 *  if
	 *                   (nodeActivation != null) {
	 *                   nodeActivations.addValue(nodeActivation);
	 *  }
	 *  }
	 *  
	 *                   this.run(nodeActivations);
	 *  
	 * <!-- end-model-doc -->
	 * @model nodesMany="true" nodesOrdered="false"
	 * @generated
	 */
	void runNodes(EList<ActivityNode> nodes);

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * <!-- begin-model-doc -->
	 * // Activate and run the given set of nodes with the given set of edges, within
	 *                   this activation group.
	 *  
	 *                   this.createNodeActivations(nodes);
	 *                   this.createEdgeInstances(edges);
	 *  this.run(this.nodeActivations);
	 *                   
	 *  // Debug.println("[activate] Exiting.");
	 *  
	 * <!-- end-model-doc -->
	 * @model nodesMany="true" nodesOrdered="false" edgesMany="true" edgesOrdered="false"
	 * @generated
	 */
	void activate(EList<ActivityNode> nodes, EList<ActivityEdge> edges);

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * <!-- begin-model-doc -->
	 * // Terminate all node activations in the group.
	 *  
	 *                   Debug.println("[terminateAll] Terminating activation group for " +
	 *                   (this.activityExecution != null? "activity " +
	 *                   this.activityExecution.getTypes().getValue(0).name: 
	 *                   this.containingNodeActivation != null? "node " +
	 *                   this.containingNodeActivation.node.name:
	 *  "expansion region") +
	 *                   ".");
	 *  
	 *  ActivityNodeActivationList nodeActivations =
	 *                   this.nodeActivations;
	 *  for (int i = 0; i < nodeActivations.size();
	 *                   i++) {
	 *  ActivityNodeActivation nodeActivation =
	 *                   nodeActivations.getValue(i);
	 *  nodeActivation.terminate();
	 *                   }
	 *  
	 *  
	 * <!-- end-model-doc -->
	 * @model
	 * @generated
	 */
	void terminateAll();

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * <!-- begin-model-doc -->
	 * // Add activity node activations for the given set of nodes to this group and
	 *                   create edge instances between them.
	 *  
	 *  for (int i = 0; i <
	 *                   nodes.size(); i++) {
	 *  ActivityNode node = nodes.getValue(i);
	 *                   
	 *  Debug.println("[createNodeActivations] Creating a node activation for "
	 *                   + node.name + "...");
	 *  this.createNodeActivation(node);
	 *  
	 *                   }
	 *  
	 *  
	 * <!-- end-model-doc -->
	 * @model nodesMany="true" nodesOrdered="false"
	 * @generated
	 */
	void createNodeActivations(EList<ActivityNode> nodes);

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * <!-- begin-model-doc -->
	 * // Create an activity node activation for a given activity node in this
	 *                   activity node activation group.
	 *  
	 *  ActivityNodeActivation
	 *                   activation =
	 *                   (ActivityNodeActivation)(this.getActivityExecution().locus.factory.instantiateVisitor(node));
	 *                   activation.node = node;
	 *  activation.running = false;
	 *  
	 *                   this.addNodeActivation(activation);
	 *  
	 *                   activation.createNodeActivations();
	 *  
	 *  return activation;
	 *                 
	 * <!-- end-model-doc -->
	 * @model required="true" ordered="false" nodeRequired="true" nodeOrdered="false"
	 * @generated
	 */
	ActivityNodeActivation createNodeActivation(ActivityNode node);

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * <!-- begin-model-doc -->
	 * // Add the given node activation to this group.
	 *  
	 *                   activation.group = this;
	 *                   this.nodeActivations.addValue(activation);
	 *  
	 * <!-- end-model-doc -->
	 * @model activationRequired="true" activationOrdered="false"
	 * @generated
	 */
	void addNodeActivation(ActivityNodeActivation activation);

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * <!-- begin-model-doc -->
	 * // Return the node activation (if any) in this group, 
	 *  // or any
	 *                   nested group, corresponding to the given activity node.
	 *  // If this is a
	 *                   group for a structured activity node activation, 
	 *  // also include the pin
	 *                   activations for that node activation.
	 *  
	 *  ActivityNodeActivation
	 *                   activation = null;
	 *  
	 *  if (this.containingNodeActivation != null
	 *                   && node instanceof Pin) {
	 *  activation =
	 *                   this.containingNodeActivation.getPinActivation((Pin)node);
	 *  }
	 *                   
	 *  if (activation == null) {
	 *  int i = 1;
	 *  while (activation
	 *                   == null & i <= this.nodeActivations.size()) { 
	 *  activation
	 *                   = this.nodeActivations.getValue(i-1).getNodeActivation(node);
	 *  i = i +
	 *                   1;
	 *  }
	 *  }
	 *  
	 *  return activation;
	 *  
	 * <!-- end-model-doc -->
	 * @model ordered="false" nodeRequired="true" nodeOrdered="false"
	 * @generated
	 */
	ActivityNodeActivation getNodeActivation(ActivityNode node);

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * <!-- begin-model-doc -->
	 * // Create instance edges for the given activity edges, as well as for edge
	 *                   instances within any nodes activated in this group.
	 *  
	 *  for (int i
	 *                   = 0; i < edges.size(); i++) {
	 *  ActivityEdge edge =
	 *                   edges.getValue(i);
	 *  
	 *  Debug.println("[createEdgeInstances]
	 *                   Creating an edge instance from " + edge.source.name + " to " + edge.target.name +
	 *                   ".");
	 *  
	 *  ActivityEdgeInstance edgeInstance = new
	 *                   ActivityEdgeInstance();
	 *  edgeInstance.edge = edge;
	 *  
	 *                   this.addEdgeInstance(edgeInstance);
	 *                   this.getNodeActivation(edge.source).addOutgoingEdge(edgeInstance);
	 *                   this.getNodeActivation(edge.target).addIncomingEdge(edgeInstance);
	 *                   
	 *  // Debug.println("[createEdgeInstances] Edge instance
	 *                   created...");
	 *  }
	 *  
	 *  ActivityNodeActivationList
	 *                   nodeActivations = this.nodeActivations;
	 *  for (int i = 0; i <
	 *                   nodeActivations.size(); i++) {
	 *  ActivityNodeActivation nodeActivation =
	 *                   nodeActivations.getValue(i);
	 *                   nodeActivation.createEdgeInstances();
	 *  }
	 *  
	 *  //
	 *                   Debug.println("[createEdgeInstances] Done creating edge instances.");
	 *                 
	 * <!-- end-model-doc -->
	 * @model edgesMany="true" edgesOrdered="false"
	 * @generated
	 */
	void createEdgeInstances(EList<ActivityEdge> edges);

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * <!-- begin-model-doc -->
	 * // Add the given edge instance to this group.
	 *  
	 *                   instance.group = this;
	 *  this.edgeInstances.addValue(instance);
	 *                 
	 * <!-- end-model-doc -->
	 * @model instanceRequired="true" instanceOrdered="false"
	 * @generated
	 */
	void addEdgeInstance(ActivityEdgeInstance instance);

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * <!-- begin-model-doc -->
	 * // Return the activity execution to which this group belongs, directly or
	 *                   indirectly.
	 *  
	 *  ActivityExecution activityExecution =
	 *                   this.activityExecution;
	 *  if (activityExecution == null) {
	 *                   activityExecution =
	 *                   this.containingNodeActivation.group.getActivityExecution();
	 *  }
	 *                   
	 *  // Debug.println("[getActivityExecution] activityExecution = " +
	 *                   activityExecution);
	 *  
	 *  return activityExecution;
	 *  
	 * <!-- end-model-doc -->
	 * @model required="true" ordered="false"
	 * @generated
	 */
	ActivityExecution fUML_getActivityExecution();

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * <!-- begin-model-doc -->
	 * // Return the set of all activations in this group of activity parameter nodes
	 *                   for output (inout, out and return) parameters.
	 *  
	 *                   ActivityParameterNodeActivationList parameterNodeActivations = new
	 *                   ActivityParameterNodeActivationList();
	 *  ActivityNodeActivationList
	 *                   nodeActivations = this.nodeActivations;
	 *  for (int i = 0; i <
	 *                   nodeActivations.size(); i++) {
	 *  ActivityNodeActivation activation =
	 *                   nodeActivations.getValue(i);
	 *  if (activation instanceof
	 *                   ActivityParameterNodeActivation) {
	 *  ParameterDirectionKind direction =
	 *                   ((ActivityParameterNode)(activation.node)).parameter.direction;
	 *  if
	 *                   ((direction.equals(ParameterDirectionKind.inout)) |
	 *                   (direction.equals(ParameterDirectionKind.out)) |
	 *                   (direction.equals(ParameterDirectionKind.return_))) {
	 *                   parameterNodeActivations.addValue((ActivityParameterNodeActivation)activation);
	 *                   }
	 *  }
	 *  }
	 *  
	 *  return
	 *                   parameterNodeActivations;
	 *  
	 * <!-- end-model-doc -->
	 * @model kind="operation" ordered="false"
	 * @generated
	 */
	EList<ActivityParameterNodeActivation> getOutputParameterNodeActivations();

} // ActivityNodeActivationGroup
